// fixme: alert chName to continue logging
// fixme: same user change data at same time(read back in setConfig..)
// v fixme: passwd reminder
// v todo: block user by login while error login for many times.
// v todo: show password hint while passwd not correct.
// fixme: check setWidth() for layout

var accountMgm = new function() { 
  this.memberDocKey = "0Av3qQfGSzCo4dDVSQjBhNVdKVFEtcndXQnJfQVBDUVE"; //義勇隊員名冊
  this.memberSheetName = "名冊(完整)";
  this.configSheetName = "組態";
  this.mobileLength = 10;
  this.maxFailedLogin = 6;
  this.showPasswdHintIn = 1;
  this.maxLevenshteinDistance = 4;
  this.version = "002";
}  
    
    
var passwdOK = ["abc123ab","qwe456rt","timchen543"];    
 

var passwdRuleTxt = 
    "新密碼長度至少要為8,不得超過20,"+
    "至少包含兩個數字(0-9)和兩個英文字母(a-z,A-Z),"+
    "不得出現四個以上(含)順序連續的字元(如:abcd,1234),"+
    "不得出現四個以上(含)鍵盤上的連續字元排列(如:qwer),"+
    "合乎規格的密碼如:"+passwdOK+
    "(這三個範例也不能用)";  

function doGet(e) {
  if( e == undefined )
    return app;
  
  Logger.log(e);
  var app = UiApp.createApplication().setTitle('Account Management');    
  
  var loginForm = app.createFormPanel().setId('loginForm').setEncoding('multipart/form-data').setVisible(true);
  app.add(loginForm);

  var loginFormContent = app.createGrid().resize(5,4);
  loginForm.add(loginFormContent);

  var loginInfoLabel = app.createLabel().setId('loginInfoLabel').setWidth('400').
      setText("預設密碼是西元的生日年份加身份證字號後四碼,登入後請進[更改密碼]改預設密碼,才可以開始使用系統.如果忘記新設定的密碼,請與文宣組聯絡.");
  loginFormContent.setWidget(0, 3, loginInfoLabel);
  
  loginFormContent.setWidget(1, 0, app.createLabel().setText('隊號:').setWidth('100%'));
  var idText = app.createTextBox().setName('idText').setId('idText').setWidth('100%');
  loginFormContent.setWidget(1, 1, idText);
  loginFormContent.setWidget(1, 3, app.createLabel().setText("(你的義勇隊號,例如:100203)"));
  /*
  loginFormContent.setText(2, 0, '姓名:');
  var nameText = app.createTextBox().setName('nameText').setId('nameText');
  loginFormContent.setWidget(2, 1, nameText);  
  */
  
  loginFormContent.setText(2, 0, '密碼:');
  var passwdText = app.createPasswordTextBox().setName('passwdText').setId('passwdText');
  loginFormContent.setWidget(2, 1, passwdText);  
  loginFormContent.setWidget(2, 3, app.createLabel().setText("(預設密碼範例格式:19801234)(1980是西元生日年份,1234是身份證後四碼)"));  
  
  var loginButton = app.createButton('登入').setId('loginButton');
  loginFormContent.setWidget(3, 1, loginButton);  
  
  var handlerLogin = app.createServerClickHandler('procLogin');
  handlerLogin.addCallbackElement(loginFormContent);  
  loginButton.addClickHandler(handlerLogin);  
  loginButton.addClickHandler(app.createClientHandler().
                              forEventSource().setEnabled(false).
                              forTargets(loginInfoLabel).setText("登入中...").
                              setStyleAttribute('color','blue'));
                              //forTargets(idText).setEnabled(false).
                              //forTargets(passwdText).setEnabled(false));
                     
  // mainForm
  var mainForm = app.createFormPanel().setId('mainForm').setEncoding('multipart/form-data').setVisible(false);
  app.add(mainForm);

  var mainFormContent = app.createGrid().resize(8,3).setId('mainFormContent');
  mainForm.add(mainFormContent);

  var mainInfoLabel = app.createLabel().setId('mainInfoLabel');
  app.getElementById('mainInfoLabel').setText('請選擇...'); 
  mainFormContent.setWidget(0, 1, mainInfoLabel);  
  mainFormContent.setWidget(0, 0, app.createLabel().setText("[主頁]"));  

  var passwdButton = app.createButton('更改密碼').setId('passwdButton');
  mainFormContent.setWidget(1, 1, passwdButton);  
  var handlerPasswd = app.createServerClickHandler('procPasswd');
  handlerPasswd.addCallbackElement(mainFormContent);  
  //passwdButton.addClickHandler(handlerPasswd);  
  
  var infoSetupButton = app.createButton('基本資料設定').setId('infoSetupButton');//.setVisible(false);
  mainFormContent.setWidget(2, 1, infoSetupButton);  
  var handlerInfoSetup = app.createServerClickHandler('procInfoSetup'); 
  infoSetupButton.addClickHandler(handlerInfoSetup);  

  var commSetupButton = app.createButton('通訊設定').setId('commSetupButton');
  mainFormContent.setWidget(4, 1, commSetupButton);  
  var handlerCommSetup = app.createServerClickHandler('procCommSetup');
  commSetupButton.addClickHandler(handlerCommSetup); 
  
  var licenseButton = app.createButton('證件設定').setId('licenseButton');
  mainFormContent.setWidget(3, 1, licenseButton);  
  var handlerLisense = app.createServerClickHandler('procLicense');
  licenseButton.addClickHandler(handlerLisense);   
  
  
  var logoutButton = app.createButton('登出').setId('logoutButton');
  mainFormContent.setWidget(6, 1, logoutButton);    
  var handlerLogout = app.createServerClickHandler('procLogout'); 
  logoutButton.addClickHandler(handlerLogout);  
 
  
  // passwdForm
  var passwdForm = app.createFormPanel().setId('passwdForm').setEncoding('multipart/form-data').setVisible(false);
  app.add(passwdForm);

  var passwdFormContent = app.createGrid().resize(7,4).setId('passwdFormContent');
  passwdForm.add(passwdFormContent);
  
  passwdFormContent.setWidget(0, 0, app.createLabel().setText("[密碼設定]")); 
  var passwdInfoLabel = app.createLabel().setId('passwdInfoLabel').setWidth('300');
  passwdFormContent.setWidget(0, 2, passwdInfoLabel); 
  
  passwdFormContent.setWidget(1, 0, app.createLabel().setText("舊密碼:"));   
  var oldPasswdText = app.createTextBox().setName('oldPasswdText').setId('oldPasswdText');//.setWidth("20%");
  passwdFormContent.setWidget(1, 1, oldPasswdText);    
  
  passwdFormContent.setWidget(2, 0, app.createLabel().setText("新密碼:"));   
  var newPasswdText = app.createTextBox().setName('newPasswdText').setId('newPasswdText');//.setWidth("20%");
  passwdFormContent.setWidget(2, 1, newPasswdText);   
  
  passwdFormContent.setWidget(3, 0, app.createLabel().setText("再次輸入新密碼:"));   
  var newPasswdText2 = app.createTextBox().setName('newPasswdText2').setId('newPasswdText2');//.setWidth("20%");
  passwdFormContent.setWidget(3, 1, newPasswdText2); 
  
  passwdFormContent.setWidget(4, 0, app.createLabel().setText("新密碼提示:"));   
  var passwdHintText = app.createTextBox().setName('passwdHintText').setId('passwdHintText');//.setWidth("20%");
  passwdFormContent.setWidget(4, 1, passwdHintText); 
  passwdFormContent.setWidget(4, 2, app.createLabel().setText("(如果你忘了新設定的密碼,這提示將會出現提醒)")); 
  
  
  
  var passwdChangeButton = app.createButton('確定修改').setId('passwdChangeButton');
  passwdFormContent.setWidget(5, 1, passwdChangeButton);  
  var handlerPasswdChange = app.createServerClickHandler('procPasswdChange');
  handlerPasswdChange.addCallbackElement(passwdFormContent);  
  passwdChangeButton.addClickHandler(handlerPasswdChange);    
  
  var passwdBackButton = app.createButton('回上頁').setId('passwdBackButton');
  passwdFormContent.setWidget(5, 0, passwdBackButton);  
  var handlerPasswdBack = app.createServerClickHandler('procPasswdBack');
  handlerPasswdBack.addCallbackElement(passwdFormContent);  
  //passwdBackButton.addClickHandler(handlerPasswdBack);    
  
     
  
  
  // infoSetupForm
  var infoSetupForm = app.createFormPanel().setId('infoSetupForm').setEncoding('multipart/form-data').setVisible(false);
  app.add(infoSetupForm);

  var infoSetupFormContent = app.createGrid().resize(16,4).setId('infoSetupFormContent');
  infoSetupForm.add(infoSetupFormContent);

  var infoSetupInfoLabel = app.createLabel().setId('infoSetupInfoLabel');
  app.getElementById('infoSetupInfoLabel');//.setText('姓名,國籍,身份證號碼,生日 如要修改請與文宣組聯絡'); 
  infoSetupFormContent.setWidget(0, 3, infoSetupInfoLabel);  
  
  var infoSetupInfoLabel2 = app.createLabel().setId('infoSetupInfoLabel2');
  app.getElementById('infoSetupInfoLabel2');//.setText('姓名,國籍,身份證號碼,生日 如要修改請與文宣組聯絡'); 
  infoSetupFormContent.setWidget(0, 1, infoSetupInfoLabel2);   
  
  infoSetupFormContent.setWidget(0, 0, app.createLabel().setText("[基本資料設定]"));  
  
  //國籍    身份證或護照號碼    生日    性別
  
  infoSetupFormContent.setWidget(1, 0, app.createLabel().setText("姓名(中文):"));   
  var chNameText = app.createTextBox().setName('chNameText').setId('chNameText').setEnabled(false).setWidth("150");
  infoSetupFormContent.setWidget(1, 1, chNameText);     
  
  infoSetupFormContent.setWidget(2, 0, app.createLabel().setText("國籍:"));   
  var nationalityText = app.createTextBox().setName('nationalityText').setId('nationalityText').setEnabled(false).setWidth("150");
  infoSetupFormContent.setWidget(2, 1, nationalityText);   

  infoSetupFormContent.setWidget(3, 0, app.createLabel().setText("身份證或護照號碼:"));   
  var nationalIDText = app.createTextBox().setName('nationalIDText').setId('nationalIDText').setEnabled(false).setWidth("150");
  infoSetupFormContent.setWidget(3, 1, nationalIDText);   
  
  infoSetupFormContent.setWidget(4, 0, app.createLabel().setText("生日:"));   
  var birthdayText = app.createTextBox().setName('birthdayText').setId('birthdayText').setEnabled(false).setWidth("150");
  infoSetupFormContent.setWidget(4, 1, birthdayText);   

  /*
  infoSetupFormContent.setWidget(5, 0, app.createLabel().setText("性別:"));   
  var sexText = app.createTextBox().setName('sexText').setId('sexText').setEnabled(false);
  infoSetupFormContent.setWidget(5, 1, sexText);   
  */
  
  //電話(手機)  電話(市話1) 電話(市話2) 通訊地址    Email  
  infoSetupFormContent.setWidget(6, 0, app.createLabel().setText("姓名(英文):"));   
  var engNameText = app.createTextBox().setName('engNameText').setId('engNameText').setEnabled(true).setWidth("300");
  infoSetupFormContent.setWidget(6, 1, engNameText); 
  infoSetupFormContent.setWidget(6, 3, app.createLabel().
                                 setText("有護照就填寫護照上英文姓名,"+
                                         "格式:LI,DA FA(李,大發)(姓放前面,然後逗點,然後名)(不要使用'-'當分隔符號),"+
                                         "姓名英譯查詢 http://www.englishname.org/"));   

  infoSetupFormContent.setWidget(7, 0, app.createLabel().setText("電話(手機):"));   
  var mobileText = app.createTextBox().setName('mobileText').setId('mobileText').setEnabled(true).setWidth("300");
  infoSetupFormContent.setWidget(7, 1, mobileText); 
  infoSetupFormContent.setWidget(7, 3, app.createLabel().setText("(建議填) 活動,服勤通知用, 範例格式: 0937019628 (不要輸入任何不是數字的字元)"));    

  infoSetupFormContent.setWidget(8, 0, app.createLabel().setText("電話(市話1):"));   
  var phone1Text = app.createTextBox().setName('phone1Text').setId('phone1Text').setEnabled(true).setWidth("300");
  infoSetupFormContent.setWidget(8, 1, phone1Text);   
  infoSetupFormContent.setWidget(8, 3, app.createLabel().setText("範例格式: (02)23066387 (不要使用'-'當分隔符號,分機號碼分隔符號是'#')"));
  
  infoSetupFormContent.setWidget(9, 0, app.createLabel().setText("電話(市話2):"));   
  var phone2Text = app.createTextBox().setName('phone2Text').setId('phone2Text').setEnabled(true).setWidth("300");
  infoSetupFormContent.setWidget(9, 1, phone2Text);   
  infoSetupFormContent.setWidget(9, 3, app.createLabel().setText(""));  
  
  infoSetupFormContent.setWidget(10, 0, app.createLabel().setText("郵遞區號:"));   
  var zipText = app.createTextBox().setName('zipText').setId('zipText').setEnabled(true).setWidth("300");
  infoSetupFormContent.setWidget(10, 1, zipText);   
  infoSetupFormContent.setWidget(10, 3, app.createLabel().
                                 setText("(必填) 查詢五碼郵遞區號 http://www.moneymanager.url.tw/台灣3+2郵遞區號查詢系統.htm"));   
  
  infoSetupFormContent.setWidget(11, 0, app.createLabel().setText("通訊地址:"));   
  var addressText = app.createTextBox().setName('addressText').setId('addressText').setEnabled(true).setWidth("300");
  infoSetupFormContent.setWidget(11, 1, addressText);   
  infoSetupFormContent.setWidget(11, 3, app.createLabel().setText("(必填) 用於寄送隊訊,隊部刊物"));    
  
  infoSetupFormContent.setWidget(12, 0, app.createLabel().setText("Email:"));   
  var emailText = app.createTextBox().setName('emailText').setId('emailText').setEnabled(true).setWidth("300");
  infoSetupFormContent.setWidget(12, 1, emailText); 
  infoSetupFormContent.setWidget(12, 3, app.createLabel().setText("(建議填) 活動,服勤通知用"));    

  var infoChangeButton = app.createButton('確定修改').setId('infoChangeButton');
  infoSetupFormContent.setWidget(14, 1, infoChangeButton);  
  var handlerInfoChange = app.createServerClickHandler('procInfoChange');
  handlerInfoChange.addCallbackElement(infoSetupFormContent);  
  infoChangeButton.addClickHandler(handlerInfoChange);    
  
  var infoBackButton = app.createButton('回上頁').setId('infoBackButton');
  infoSetupFormContent.setWidget(14, 0, infoBackButton);  
  var handlerInfoBack = app.createServerClickHandler('procInfoBack');
  handlerInfoBack.addCallbackElement(infoSetupFormContent);  
  //infoBackButton.addClickHandler(handlerInfoBack);  
  
  

  // commSetupForm
  var commSetupForm = app.createFormPanel().setId('commSetupForm').setEncoding('multipart/form-data').setVisible(false);
  app.add(commSetupForm);
  
  var commSetupFormContent = app.createGrid().resize(6,8).setId('commSetupFormContent');
  commSetupForm.add(commSetupFormContent);
 

  commSetupFormContent.setWidget(0, 7, app.createLabel().
                                 setText("愛護地球請少用紙本通訊").
                                 setStyleAttribute('color','green'));
  
  var commSetupInfoLabel = app.createLabel().setId('commSetupInfoLabel');
  app.getElementById('commSetupInfoLabel').setText(''); 
  commSetupFormContent.setWidget(0, 6, commSetupInfoLabel);   
  
  
  
  commSetupFormContent.setWidget(0, 0, app.createLabel().setText("[通訊設定]"));
  
  commSetupFormContent.setWidget(1, 0, app.createLabel().setText("活動通知:"));
  var actEMCheckbox = app.createCheckBox().setName('actEMCheckbox').setId('actEMCheckbox'); 
  commSetupFormContent.setWidget(1, 1, actEMCheckbox);//.setWidth("100%");
  var actEMInfoLabel = app.createLabel().setText("Email").setId('actEMInfoLabel');
  commSetupFormContent.setWidget(1, 2, actEMInfoLabel);//.setWidth("100%");
  var actSMCheckbox = app.createCheckBox().setName('actSMCheckbox').setId('actSMCheckbox');
  commSetupFormContent.setWidget(1, 3, actSMCheckbox);//.setWidth("100%");
  var actSMInfoLabel = app.createLabel().setText("簡訊").setId('actSMInfoLabel');
  commSetupFormContent.setWidget(1, 4, actSMInfoLabel);//.setWidth("100%");
  commSetupFormContent.setWidget(1, 6, app.createLabel().setText("(例如: 服勤提醒)")); 
  
  commSetupFormContent.setWidget(2, 0, app.createLabel().setText("重點刊物:"));
  var majorEMCheckbox = app.createCheckBox().setName('majorEMCheckbox').setId('majorEMCheckbox'); 
  commSetupFormContent.setWidget(2, 1, majorEMCheckbox);//.setWidth("100%");
  var majorEMInfoLabel = app.createLabel().setText("Email").setId('majorEMInfoLabel');
  commSetupFormContent.setWidget(2, 2, majorEMInfoLabel);//.setWidth("100%");
  var majorPACheckbox = app.createCheckBox().setName('majorPACheckbox').setId('majorPACheckbox');
  commSetupFormContent.setWidget(2, 3, majorPACheckbox);//.setWidth("100%");
  var majorPAInfoLabel = app.createLabel().setText("紙本").setId('majorPAInfoLabel');
  commSetupFormContent.setWidget(2, 4, majorPAInfoLabel);//.setWidth("100%");
  commSetupFormContent.setWidget(2, 6, app.createLabel().setText("(例如: 隊部年度發行刊物)"));

  commSetupFormContent.setWidget(3, 0, app.createLabel().setText("次重點刊物:"));
  var minorEMCheckbox = app.createCheckBox().setName('minorEMCheckbox').setId('minorEMCheckbox'); 
  commSetupFormContent.setWidget(3, 1, minorEMCheckbox);//.setWidth("100%");
  var minorEMInfoLabel = app.createLabel().setText("Email").setId('minorEMInfoLabel');
  commSetupFormContent.setWidget(3, 2, minorEMInfoLabel);//.setWidth("100%");
  var minorPACheckbox = app.createCheckBox().setName('minorPACheckbox').setId('minorPACheckbox');
  commSetupFormContent.setWidget(3, 3, minorPACheckbox);//.setWidth("100%");
  var minorPAInfoLabel = app.createLabel().setText("紙本").setId('minorPAInfoLabel');
  commSetupFormContent.setWidget(3, 4, minorPAInfoLabel);//.setWidth("100%");
  commSetupFormContent.setWidget(3, 6, app.createLabel().setText("(例如: 例行性隊訊)"));
  
  var commChangeButton = app.createButton('確定修改').setId('commChangeButton');
  commSetupFormContent.setWidget(5, 6, commChangeButton);  
  var handlerCommChange = app.createServerClickHandler('procCommChange');
  handlerCommChange.addCallbackElement(commSetupFormContent);  
  commChangeButton.addClickHandler(handlerCommChange);    
  
  var commBackButton = app.createButton('回上頁').setId('commBackButton');
  commSetupFormContent.setWidget(5, 0, commBackButton);      
  
  
  // licenseForm
  var licenseForm = app.createFormPanel().setId('licenseForm').setEncoding('multipart/form-data').setVisible(false);
  app.add(licenseForm);
  
  var licenseFormContent = app.createGrid().resize(7,19).setId('licenseFormContent');
 // licenseFormContent.setStyleAttribute('border','1px solid');
  licenseForm.add(licenseFormContent);
  
  licenseFormContent.setText(0,0,"[證件管理]");
  licenseFormContent.setText(1,1,"證件");
  licenseFormContent.setText(1,2,"發照日"); // 2,3 4,5 6,7
  licenseFormContent.setText(1,9,"到期日"); // 9,10 11,12 13,14
  
  var licenseInfoLabel = app.createLabel().setId('licenseInfoLabel');
  app.getElementById('licenseInfoLabel').setText(''); 
  licenseFormContent.setWidget(0, 1, licenseInfoLabel);   
  
  
  
  /*
  var licenseList = app.createListBox().setId('licenseList');
  licenseFormContent.setWidget(2, 1, licenseList);
  
  var date1YearText = app.createTextBox().setName('date1YearText').setId('date1YearText').setWidth("40");
  licenseFormContent.setWidget(2, 2, date1YearText);   
  licenseFormContent.setText(2,3,"年");
  
  var date1MonthText = app.createTextBox().setName('date1MonthText').setId('date1MonthText').setWidth("25");
  licenseFormContent.setWidget(2, 4, date1MonthText);   
  licenseFormContent.setText(2,5,"月");
  
  var date1DayText = app.createTextBox().setName('date1DayText').setId('date1DayText').setWidth("25");
  licenseFormContent.setWidget(2, 6, date1DayText);   
  licenseFormContent.setText(2,7,"日");  
  
  
  licenseFormContent.setText(2,8,"-");
  
  
  var date2YearText = app.createTextBox().setName('date2YearText').setId('date2YearText').setWidth("40");
  licenseFormContent.setWidget(2, 9, date2YearText);   
  licenseFormContent.setText(2,10,"年");
  
  var date2MonthText = app.createTextBox().setName('date2MonthText').setId('date2MonthText').setWidth("25");
  licenseFormContent.setWidget(2, 11, date2MonthText);   
  licenseFormContent.setText(2,12,"月");
  
  var date2DayText = app.createTextBox().setName('date2DayText').setId('date2DayText').setWidth("25");
  licenseFormContent.setWidget(2, 13, date2DayText);   
  licenseFormContent.setText(2,14,"日");    
  
  */
    
  /*  
  var licenseAddButton = app.createButton('新增證件').setId('licenseAddButton');
  licenseFormContent.setWidget(2, 16, licenseAddButton);    
  var handlerLicenseAdd = app.createServerClickHandler('procLicenseAdd');
  handlerLicenseAdd.addCallbackElement(licenseFormContent);  
  licenseAddButton.addClickHandler(handlerLicenseAdd);    
  */
  

  var licenseChangeButton = app.createButton('確定修改').setId('licenseChangeButton');
  //licenseFormContent.setWidget(5, 16, licenseChangeButton);  
  var handlerLicenseChange = app.createServerClickHandler('procLicenseChange');
  handlerLicenseChange.addCallbackElement(licenseFormContent);  
  licenseChangeButton.addClickHandler(handlerLicenseChange);    
  
  
  var licenseBackButton = app.createButton('回上頁').setId('licenseBackButton');
  //licenseFormContent.setWidget(5, 0, licenseBackButton);      
    
  
  
  
  // logoutForm
  var logoutForm = app.createFormPanel().setId('logoutForm').setEncoding('multipart/form-data').setVisible(false);
  app.add(logoutForm);
  
  var logoutFormContent = app.createGrid().resize(6,8).setId('logoutFormContent');
  logoutForm.add(logoutFormContent);
  logoutFormContent.setWidget(0, 2, app.createLabel().setText("謝謝使用!"));
  
  logoutButton.addClickHandler(app.createClientHandler().
                               forEventSource().setEnabled(false).
                               forTargets(mainForm).setVisible(false).
                               forTargets(logoutForm).setVisible(true));
  
  
  
  // button client action.

  passwdButton.addClickHandler(app.createClientHandler().
                               forEventSource().setEnabled(false).
                               forTargets(passwdInfoLabel).setText(passwdRuleTxt).setStyleAttribute('color','black').
                               forTargets(passwdChangeButton).setEnabled(true).
                               forTargets(passwdBackButton).setEnabled(true). 
                               forTargets(passwdForm).setVisible(true).
                               forTargets(mainForm).setVisible(false));
  
                               //forTargets(infoSetupButton).setEnabled(false));//.
                             //  forTargets(logoutButton).setEnabled(false).
                             //  forTargets(commSetupButton).setEnabled(false));
  
  passwdChangeButton.addClickHandler(app.createClientHandler().
                                     forEventSource().setEnabled(false).
                                     forTargets(passwdBackButton).setEnabled(false). 
                                     forTargets(passwdInfoLabel).setText("設定中..").
                                     setStyleAttribute('color','blue').
                                     forTargets(oldPasswdText).setText("").
                                     forTargets(newPasswdText).setText("").
                                     forTargets(newPasswdText2).setText("").                                     
                                     forTargets(passwdHintText).setText(""));
       
  passwdBackButton.addClickHandler(app.createClientHandler().
                                   forEventSource().setEnabled(false).
                                   forTargets(mainInfoLabel).setText("").setStyleAttribute('color','black').
                                   forTargets(passwdButton).setEnabled(true).
                                   forTargets(logoutButton).setEnabled(true).
                                   forTargets(passwdForm).setVisible(false).
                                   forTargets(mainForm).setVisible(true));
  
  
  /*
                                   forTargets(infoSetupButton).setEnabled(true).
                                   forTargets(commSetupButton).setEnabled(true).
                                   forTargets(licenseButton).setEnabled(true).
*/
    
  var infoTxt = '姓名,國籍,身份證號碼,生日 如要修改請與文宣組聯絡';
  var textBoxes = new Array(chNameText,
                            engNameText,
                            nationalityText,
                            nationalIDText,
                            birthdayText,
                            mobileText,
                            phone1Text,
                            phone2Text,
                            zipText,
                            addressText,
                            emailText);
  
  var clientHandlerInfoSetup = app.createClientHandler().
      forEventSource().setEnabled(false).
      forTargets(infoSetupFormContent).setEnabled(false).
      forTargets(infoChangeButton).setEnabled(false).
      forTargets(infoBackButton).setEnabled(false).    
      forTargets(infoSetupInfoLabel2).setText("").setStyleAttribute('color','blue').
      forTargets(infoSetupInfoLabel).setText(infoTxt).setStyleAttribute('color','black').
      forTargets(mainForm).setVisible(false).
      forTargets(infoSetupForm).setVisible(true).setEnabled(false);
  
  for( var i=0; i<textBoxes.length; i++ ) {
    clientHandlerInfoSetup = clientHandlerInfoSetup.
      forTargets(textBoxes[i]).
      setText("資料讀取中..請稍後..").
      setEnabled(false).
      setStyleAttribute('color','blue');
  }
  infoSetupButton.addClickHandler(clientHandlerInfoSetup);
  /*
  infoSetupButton.addClickHandler(app.createClientHandler().
                                  forEventSource().setEnabled(false).
                                  forTargets(mainForm).setVisible(false).
                                  forTargets(infoSetupForm).setVisible(true).setEnabled(false).
                                  forTargets(infoSetupFormContent).setEnabled(false).
                                  forTargets(infoChangeButton).setEnabled(true).
                                  forTargets(infoBackButton).setEnabled(true).    
                                  forTargets(infoSetupInfoLabel2).setText("資料讀取中..請稍後..").setStyleAttribute('color','blue').
                                  forTargets(infoSetupInfoLabel).setText(infoTxt).setStyleAttribute('color','black'));  
  */
  infoBackButton.addClickHandler(app.createClientHandler().
                                 forEventSource().setEnabled(false).
                                 forTargets(passwdButton).setEnabled(true).
                                 forTargets(infoSetupButton).setEnabled(true).
                                 forTargets(commSetupButton).setEnabled(true).
                                 forTargets(logoutButton).setEnabled(true).
                                 forTargets(mainInfoLabel).setText("").setStyleAttribute('color','black').
                                 forTargets(infoSetupForm).setVisible(false).
                                 forTargets(mainForm).setVisible(true));
  
  infoChangeButton.addClickHandler(app.createClientHandler().
                                   forEventSource().setEnabled(false).
                                   forTargets(infoBackButton).setEnabled(false).  
                                   forTargets(infoSetupInfoLabel).setText(""));    
 
  commSetupButton.addClickHandler(app.createClientHandler().
                                  forEventSource().setEnabled(false). 
                                  forTargets(commChangeButton).setEnabled(false).
                                  forTargets(commBackButton).setEnabled(false).
                                  forTargets(actEMCheckbox).setValue(false).setEnabled(false).
                                  forTargets(actSMCheckbox).setValue(false).setEnabled(false).
                                  forTargets(majorEMCheckbox).setValue(false).setEnabled(false).
                                  forTargets(majorPACheckbox).setValue(false).setEnabled(false).
                                  forTargets(minorEMCheckbox).setValue(false).setEnabled(false).
                                  forTargets(minorPACheckbox).setValue(false).setEnabled(false).
                                  forTargets(actEMInfoLabel).setEnabled(false).setStyleAttribute('color','gray').
                                  forTargets(actSMInfoLabel).setEnabled(false).setStyleAttribute('color','gray').
                                  forTargets(majorEMInfoLabel).setEnabled(false).setStyleAttribute('color','gray').
                                  forTargets(majorPAInfoLabel).setEnabled(false).setStyleAttribute('color','gray').
                                  forTargets(minorEMInfoLabel).setEnabled(false).setStyleAttribute('color','gray').
                                  forTargets(minorPAInfoLabel).setEnabled(false).setStyleAttribute('color','gray').
                                  forTargets(commSetupInfoLabel).setText("讀取設定中..").
                                  setStyleAttribute('color','blue').
                                  forTargets(mainForm).setVisible(false).
                                  forTargets(commSetupForm).setVisible(true));
  
  //actEMCheckbox actSMCheckbox majorEMCheckbox majorPACheckbox minorEMCheckbox minorPACheckbox 
  //actEMInfoLabel actSMInfoLabel majorEMInfoLabel majorPAInfoLabel minorEMInfoLabel minorPAInfoLabel
    
  commChangeButton.addClickHandler(app.createClientHandler().
                                   forEventSource().setEnabled(false).
                                   forTargets(commBackButton).setEnabled(false).  
                                   forTargets(commSetupInfoLabel).setText(""));   
  
  commBackButton.addClickHandler(app.createClientHandler().
                                 forTargets(passwdButton).setEnabled(true).
                                 forTargets(infoSetupButton).setEnabled(true).
                                 forTargets(commSetupButton).setEnabled(true).
                                 forTargets(logoutButton).setEnabled(true).
                                 forTargets(mainInfoLabel).setText("").setStyleAttribute('color','black').                                
                                 forTargets(commSetupForm).setVisible(false).
                                 forTargets(mainForm).setVisible(true));
  
  
  // license
  licenseButton.addClickHandler(app.createClientHandler().
                               forTargets(licenseInfoLabel).setText("設定讀取中請稍候..").setStyleAttribute('color','blue').               
                               forTargets(licenseBackButton).setEnabled(true). 
                               forTargets(licenseForm).setVisible(true).
                               forTargets(mainForm).setVisible(false));  
  

  licenseChangeButton.addClickHandler(app.createClientHandler().
                                   forEventSource().setEnabled(false).
                                   forTargets(licenseBackButton).setEnabled(false).  
                                   forTargets(licenseInfoLabel).setText("設定寫入中..").
                                   setStyleAttribute('color','blue'));   


  licenseBackButton.addClickHandler(app.createClientHandler().
                                 forTargets(passwdButton).setEnabled(true).
                                 forTargets(infoSetupButton).setEnabled(true).
                                 forTargets(commSetupButton).setEnabled(true).
                                 forTargets(logoutButton).setEnabled(true).
                                 forTargets(mainInfoLabel).setText("").setStyleAttribute('color','black').                                
                                 forTargets(licenseForm).setVisible(false).
                                 forTargets(mainForm).setVisible(true));  
  
  
  return app;
}

function openMemberSheet() {
  try {
    var ss = SpreadsheetApp.openById(accountMgm.memberDocKey); 
  } catch(err) {
    Logger.log(err);
    return null;
  }
  
  try {
    var sheet = ss.getSheetByName(accountMgm.memberSheetName);
  } catch(err) {
    Logger.log(err);
    return null;
  }      
  
  return sheet;
}


function openConfigSheet() {
  try {
    var ss = SpreadsheetApp.openById(accountMgm.memberDocKey); 
  } catch(err) {
    Logger.log(err);
    return null;
  }
  
  try {
    var sheet = ss.getSheetByName(accountMgm.configSheetName);
  } catch(err) {
    Logger.log(err);
    return null;
  }      
  
  return sheet;
}


function procLogin(e){
  Logger.log(e);
  
  var app = UiApp.getActiveApplication();
    
  var loginID = e.parameter.idText;
  var loginPasswd = e.parameter.passwdText;
  var passed = true;
  
  if(loginID == '') {
    appMsg('loginInfoLabel','帳號錯誤!','red');   
    app.getElementById('loginButton').setEnabled(true);
    return app;
  }
  
  if(loginPasswd == '') {
    appMsg('loginInfoLabel','密碼錯誤!','red'); 
    app.getElementById('loginButton').setEnabled(true);
    return app;
  }  

  var sheet = openMemberSheet();
  if( sheet == null ) {
    appMsg('loginInfoLabel','名冊開啟錯誤!','red'); 
    app.getElementById('loginButton').setEnabled(true);
    return app;
  }  
  
  var realPasswd = getValueByKey(sheet,"隊號",loginID,"帳號密碼");
  var defaultPasswd = getValueByKey(sheet,"隊號",loginID,"帳號預設密碼");

  Logger.log("loginID="+loginID);
  Logger.log("loginPasswd="+loginPasswd);
  Logger.log("realPasswd="+realPasswd);
  Logger.log("defaultPasswd="+defaultPasswd);
  
  var rangeOKCount = getRangeByKey(sheet,"隊號",loginID,"帳號登入次數");
  var rangeFailedCount = getRangeByKey(sheet,"隊號",loginID,"帳號登入錯誤次數");

  var failedCount = rangeFailedCount.getValue();
  if( failedCount == "" ) {
    failedCount = new Number(0);
  } else {
    failedCount = parseInt(failedCount);
  }
/*  
  if((failedCount>accountMgm.showPasswdHintIn) && (failedCount<=accountMgm.maxFailedLogin)) {
    var rangePasswdHint = getRangeByKey(sheet,"隊號",loginID,"帳號密碼提醒").getValue();
    
    if( rangePasswdHint != "" ) {
      appMsg('loginInfoLabel',"你的密碼提示:"+rangePasswdHint,'blue');
    } else {
      appMsg('loginInfoLabel',"你的密碼提示:"+"如果是初次登入請使用預設密碼",'blue');
    }
    
    try{
      rangeFailedCount.setValue(++failedCount);
    } catch(err) {
      Logger.log(err); 
    }
    
    app.getElementById('loginButton').setEnabled(true);
    return app;    
  }
  
  
  if(failedCount>accountMgm.maxFailedLogin) {
    appMsg('loginInfoLabel','密碼錯誤太多次,帳號已被鎖住,無法再次登入,請聯絡文宣組.','red');
    
    try{
      rangeFailedCount.setValue(++failedCount);
    } catch(err) {
      Logger.log(err); 
    }    
    
    return app;
  }
  */
  if( loginPasswd != realPasswd ) {
    try{
      rangeFailedCount.setValue(++failedCount);
    } catch(err) {
      Logger.log(err); 
    }    
/*    
    appMsg('loginInfoLabel','帳號或密碼錯誤!','red');
    app.getElementById('loginButton').setEnabled(true);
*/
  if((failedCount>accountMgm.showPasswdHintIn) && (failedCount<=accountMgm.maxFailedLogin)) {
    var rangePasswdHint = getRangeByKey(sheet,"隊號",loginID,"帳號密碼提醒").getValue();
    
    if( rangePasswdHint != "" ) {
      appMsg('loginInfoLabel',"你的密碼提示:"+rangePasswdHint,'blue');
    } else {
      appMsg('loginInfoLabel',"你的密碼提示:"+"如果是初次登入請使用預設密碼",'blue');
    }
    
    try{
      rangeFailedCount.setValue(++failedCount);
    } catch(err) {
      Logger.log(err); 
    }
    
    app.getElementById('loginButton').setEnabled(true);
    return app;    
  }
  
  
  if(failedCount>accountMgm.maxFailedLogin) {
    appMsg('loginInfoLabel','密碼錯誤太多次,帳號已被鎖住,無法再次登入,請聯絡文宣組.','red');
    
    try{
      rangeFailedCount.setValue(++failedCount);
    } catch(err) {
      Logger.log(err); 
    }    
    
    return app;
  }    
    
    
    appMsg('loginInfoLabel','帳號或密碼錯誤!','red');
    app.getElementById('loginButton').setEnabled(true);
    
    
    return app;
  }
  
  // login & passed both ok.
  setLogin(loginID);
  setPasswd(loginPasswd);
  
  var OKCount = rangeOKCount.getValue();
  if( OKCount == "" ) {
    OKCount = new Number(0);
  } else {
    OKCount = parseInt(OKCount);
  }
  
  try{
    rangeOKCount.setValue(++OKCount);
  } catch(err) {
    Logger.log(err); 
  }
  
  // reset failed login count
  try{
    rangeFailedCount.setValue(0);
  } catch(err) {
    Logger.log(err); 
  }
  app.getElementById('loginForm').setVisible(false);
  
  if(realPasswd == defaultPasswd) {
    appMsg('mainInfoLabel',"請更改預設密碼,再繼續使用系統.",'blue');
    app.getElementById('infoSetupButton').setEnabled(false);
    app.getElementById('commSetupButton').setEnabled(false);
    app.getElementById('licenseButton').setEnabled(false);
  }
  app.getElementById('mainForm').setVisible(true); 
  
  return app;  
}

function checkPasswdHint(newPasswd,passwdHint) {
  
  var d = levenshteinenator(newPasswd,passwdHint);
  
  if( d > accountMgm.maxLevenshteinDistance )
    return true;
  
  
  return false;
}

function procPasswdChange(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();
  var loginID = getLogin();
  var loginPasswd = getPasswd();
  
  var oldPasswdText = e.parameter.oldPasswdText;
  var newPasswdText = e.parameter.newPasswdText;
  var newPasswdText2 = e.parameter.newPasswdText2;
  var passwdHintText = e.parameter.passwdHintText;
  
  Logger.log("loginID="+loginID);
  Logger.log("loginPasswd="+loginPasswd);
  Logger.log("oldPasswdText="+oldPasswdText);
  Logger.log("newPasswdText="+newPasswdText);
  Logger.log("newPasswdText2="+newPasswdText2);
  Logger.log("passwdHintText="+passwdHintText);
  
  
  if(oldPasswdText != loginPasswd) {
    appMsg('passwdInfoLabel','舊密碼不符合!','red'); 
  } else {
    if(newPasswdText != newPasswdText2) {
      appMsg('passwdInfoLabel','新密碼與再次輸入的新密碼不符合!','red'); 
    } else {
      var passwdPassed = validatePassword(
        newPasswdText2, {
          length:   [8, 20],
          alpha:    2,
          numeric:  2,
          badSequenceLength: 4,
          badWords: [passwdOK[0],passwdOK[1]],
          noSequential: false,
          noQwertySequences:true
        });    

      var passwdHintPassed = checkPasswdHint(newPasswdText2,passwdHintText.split(' ').join(''));
      
      var passwdErrorTxt = new Array();
      
      
      if( passwdHintPassed ) {
        
      } else {
        passwdErrorTxt.push("新密碼提示:與新密碼太類似,請重新設定!");
      }
      
      if( passwdPassed ) {        
        
      } else {
        passwdErrorTxt.push("新密碼:不符合規定!"+passwdRuleTxt);
      }
      
      if( passwdHintPassed && passwdPassed ) {
        
        var sheet = openMemberSheet();
        if( sheet == null ) {
          appMsg('passwdInfoLabel','名冊開啟錯誤!','red'); 
        } else {
          var rangeNewPasswd = getRangeByKey(sheet,"隊號",loginID,"帳號密碼");
          var rangePasswdHint = getRangeByKey(sheet,"隊號",loginID,"帳號密碼提醒");
          var passedNewPasswd = setValue(rangeNewPasswd,newPasswdText2);
          var passedPasswdHint = setValue(rangePasswdHint,passwdHintText);
          
          if(passedNewPasswd && passedPasswdHint) {
            appMsg('passwdInfoLabel','新密碼設定成功,下次請用新密碼登入!','green');
            setPasswd(newPasswdText2);
            
  
                                     
            app.getElementById('infoSetupButton').setEnabled(true);    
            app.getElementById('commSetupButton').setEnabled(true);    
            app.getElementById('licenseButton').setEnabled(true);                
            
          } else {
            appMsg('passwdInfoLabel','名冊檔寫入錯誤!','red');  
          }
          
        }
        
      } else {
        appMsg('passwdInfoLabel',passwdErrorTxt,'red');
      }
      
    }
  }
  
  
  app.getElementById('passwdChangeButton').setEnabled(true);
  app.getElementById('passwdBackButton').setEnabled(true);
  
  return app;
}

/*
function procPasswdBack(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();
  app.getElementById('passwdForm').setVisible(false);
  app.getElementById('mainForm').setVisible(true);   
  
  return app;  
}
*/

// input: array,array
// fixme: getElementById returns invalid object
// fixme: too specific and ugly..
function setTextBoxText(IDs,texts) {
  if(IDs.length!=texts.length)
    return false;
  
  var disabledIDs = new Array("chNameText",
                              "nationalityText",
                              "nationalIDText",
                              "birthdayText");
  
  for(var i=0;i<IDs.length;i++) {
    try{
      //Logger.log(i);
      var t = UiApp.getActiveApplication().getElementById(IDs[i]);
      t.setText(texts[i]).setEnabled(true).setStyleAttribute('color','black'); 
    } catch(err) {
      Logger.log(err);
    }
  }
  
  for(var i=0;i<disabledIDs.length;i++) {
    UiApp.getActiveApplication().getElementById(disabledIDs[i]).setEnabled(false);
  }
  
  return true;
}

//
function procInfoSetup(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();
  
  
  // fill 
  var sheet = openMemberSheet();
  
  if( sheet == null ) {
    appMsg('InfoSetupInfoLabel','名冊開啟錯誤!','red'); 
  }  else {
    
    var loginID = getLogin();
    var textBoxIDs = new Array("chNameText",
                               "engNameText",
                               "nationalityText",
                               "nationalIDText",
                               "birthdayText",
                               "mobileText",
                               "phone1Text",
                               "phone2Text",
                               "addressText",
                               "emailText");
    
    var col_values = new Array("姓名(中文)",
                               "姓名(英文)",
                               "國籍",
                               "身份證或護照號碼",
                               "生日",
                               "電話(手機)",
                               "電話(市話1)",
                               "電話(市話2)",
                               "通訊地址",
                               "Email");
    
    
    Logger.log("loginID="+loginID);
    
    
    var values = new Array();
    
    // fixme: return object instead of array
    // fixme: trim in getValuesByKey()
    values = getValuesByKey(sheet,"隊號",loginID,col_values);
    
    if( values == null ) {
      appMsg("infoSetupInfoLabel","錯誤:getValuesByKey()",'red');
    } else {
      
      // trim spaces
      for( i in values ) {
        values[i] = values[i].toString().trim();
      }
      
      var sheet_config = openConfigSheet();
      
      var nationalityConfig = {};
      nationalityConfig = getConfigString(sheet_config,"國籍");      
      values[2] = nationalityConfig[values[2]];
          
      // fixme: no directly value
      var birthday = new Date(values[4]);
      var birthday_str = "西元"+birthday.getFullYear()+"年/"+(birthday.getMonth()+1)+"月/"+birthday.getDate()+"日";
      values[4] = birthday_str;
      
      var mobile_str = new String(values[5]);
      if( mobile_str.length == 9 ) {
        mobile_str = "0"+mobile_str;
        values[5] = mobile_str;
      }
      
      //fixme: phone format
      var address_str = new String(values[8]);
      var zip_str = address_str.substring(0,address_str.indexOf(" "));
      app.getElementById('zipText').
        setText(zip_str).
        setEnabled(true).
        setStyleAttribute('color','black');
      
      address_str = address_str.substring(address_str.indexOf(" ")+1);
      values[8] = address_str;
      
      if(!setTextBoxText(textBoxIDs,values)) {
        appMsg("infoSetupInfoLabel","錯誤:setTextBoxText()",'red');
        textBoxIDs.push("zipText");
        for(var i=0;i<textBoxIDs.length;i++) {          
          app.getElementById(textBoxIDs[i]).setEnabled(false);
        }        
      } else {        
        app.getElementById('infoSetupInfoLabel2').setText("讀取完成,資料修改後請按[確定修改]進行資料登錄..");
      }
    }
  }
  
  app.getElementById('infoBackButton').setEnabled(true);
  app.getElementById('infoChangeButton').setEnabled(true);
  
  return app; 
}
  

function procInfoChange(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();

  var textBoxIDs = new Array("chNameText",
                             "engNameText",
                             "nationalityText",
                             "nationalIDText",
                             "birthdayText",
                             "mobileText",
                             "phone1Text",
                             "phone2Text",
                             "zipText",    // +
                             "addressText",
                             "emailText");
  
  
  // fixme: iterate through
  var user = {
    "chName":e.parameter.chNameText.toString().trim(),
    "engName":e.parameter.engNameText.toString().trim(),
    "nationality":e.parameter.nationalityText.toString().trim(),
    "nationalID":e.parameter.nationalIDText.toString().trim(),
    "birthday":e.parameter.birthdayText.toString().trim(),
    "mobile":e.parameter.mobileText.toString().trim(),
    "phone1":e.parameter.phone1Text.toString().trim(),
    "phone2":e.parameter.phone2Text.toString().trim(),
    "zip":e.parameter.zipText.toString().trim(),
    "address":e.parameter.addressText.toString().trim(),
    "email":e.parameter.emailText.toString().trim()
  };
  
  var passed = true;
  var formatHint = new Array();
  
  // check user's input  
  // fixme: !=""
  var reEngName = new RegExp(/^\s*[A-Za-z]{2,},[A-Za-z\s]{2,}$/);
  if( user["engName"] != "" ) {
    if(!reEngName.test(user["engName"])) {
      formatHint.push("英文姓名:格式有誤");
      passed = false;
    } 
  }
  
  //var reMobile = new RegExp(/^\s*([0-9]{10}|^[-]+)\s*$/);
  var reMobile = new RegExp(/^\s*[0-9]{10}\s*$/);
  if( user["mobile"] != "" ) {
    if( !reMobile.test(user["mobile"]) ) {
      formatHint.push("手機:格式有誤");
      passed = false;
    } 
  }
  
  var rePhone = new RegExp(/^\s*(\([0-9]+\)\s*[0-9]{5,}\s*#?\s*[0-9]{1,}|^[-]+)\s*$/);
  if( user["phone1"] != "" ) {
    if( !rePhone.test(user["phone1"]) ) {
      formatHint.push("市話1:格式有誤");
      passed = false;      
    }
  }  
  
  if( user["phone2"] != "" ) {
    if( !rePhone.test(user["phone2"]) ) {
      formatHint.push("市話2:格式有誤");
      passed = false;      
    }
  }  
  
  var reZip = new RegExp(/^\s*[0-9]{5}\s*$/);
  if( user["zip"] != "" ) {
    if( !reZip.test(user["zip"]) ) {
      formatHint.push("郵遞區號:要輸入五碼的");
      passed = false;      
    }
  } else {
    formatHint.push("郵遞區號:是必填項目");
    passed = false;
  }
  
  if( user["address"] != "" ) {
    if( isNumber(user["address"][0]) ) {
      formatHint.push("地址:郵遞區號不要輸入在地址欄前面,要輸入在郵遞區號欄");
      passed = false;      
    }
    if( user["address"].indexOf("郵政") > (-1) ) {
      formatHint.push("地址:不能輸入郵政信箱");
      passed = false;         
    }
    if( user["address"].indexOf("台北縣") > (-1) ) {
      formatHint.push("地址:台北縣已經升格,請使用新北市XX區");
      passed = false;     
    }
    if( (user["address"].indexOf("大馬路") > -1) && (user["address"].indexOf("外埔") < 0) ) {     
      formatHint.push("地址:不要搞笑..");
      passed = false;     
    }     
  } else {
    formatHint.push("地址:是必填項目");
    passed = false; 
  }
  
  var goodmail = "mail@abc.com.tw";
  if( user["email"] != "" ) {
    
    if( !checkEmail( user["email"] ) ) {
      formatHint.push("Email:格式錯誤,範例"+goodmail);
      passed = false; 
    }
    if( user["email"] == goodmail ) {
      formatHint.push("Email:不要搞笑..");
      passed = false;        
    }
  }
  
  var col_values = new Array("姓名(英文)",               
                             "電話(手機)",
                             "電話(市話1)",
                             "電話(市話2)",
                             "通訊地址",
                             "Email");
  var user_new = {
    "engName":user["engName"],
    "mobile":user["mobile"],
    "phone1":user["phone1"],
    "phone2":user["phone2"],
    "address":user["zip"]+" "+user["address"],
    "email":user["email"]
  };
  
  for( i in user_new ) {
    Logger.log(user_new[i]);
  }
  
  var sheet = openMemberSheet();
  
  if( sheet == null ) {
    appMsg('infoSetupInfoLabel','名冊開啟錯誤!','red'); 
  }  else {
    
    var loginID = getLogin();
    var ranges = new Array();
    
    if( !passed ) {  
      appMsg("infoSetupInfoLabel",formatHint.toString(),'red'); 
    } else {
      
      ranges = getRangeByKeys(sheet,"隊號",loginID,col_values);
      if( ranges == null ) {
        appMsg("infoSetupInfoLabel","錯誤:getRangeByKeys()","red");
      } else {
        
        // fixme: save changed user data only.
        var i=0;
        for( iu in user_new ) {
          ranges[i++].setValue(user_new[iu]);
        }
        
       
        SpreadsheetApp.flush();
        
        i=0;
        appMsg("infoSetupInfoLabel","資料修改成功!","green");
        
        // read back
        for( iu in user_new ) {
          if( ranges[i++].getValue().toString() != user_new[iu] ) {       
            appMsg("infoSetupInfoLabel","錯誤:名冊檔寫入,請回到主選單再設定一次!","red");
          }
        }             
      } 
    }
  }
  app.getElementById("infoChangeButton").setEnabled(true);
  app.getElementById("infoBackButton").setEnabled(true);
  
  return app;
}

/*
function procInfoBack(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();

  app.getElementById('infoSetupForm').setVisible(false);   
  app.getElementById('mainForm').setVisible(true);
  
  return app;
}
*/



function procCommSetup(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();
  appMsg('commSetupInfoLabel',"","black");

  var sheet = openMemberSheet();
  
  if( sheet == null ) {
    appMsg('commSetupInfoLabel','名冊開啟錯誤!','red'); 
  }  else {
    
    var col_values = new Array("電話(手機)",
                               "通訊地址",
                               "Email");
    var values = new Array();
    var loginID = getLogin();
    values = getValuesByKey(sheet,"隊號",loginID,col_values);
    
    if( values == null ) {
      appMsg('commSetupInfoLabel','名冊讀取錯誤!','red');      
    } else {
      var user = {
        "mobile":values[0],
        "address":values[1],
        "email":values[2]
      };
      
      for( i in user ) 
        Logger.log(user[i]);
      
      var formatHint = new Array();
      var mobilePassed = true;
      var addressPassed = true;
      var emailPassed = true;
      
      var reMobile = new RegExp(/^\s*[0-9]{10}\s*$/);
      if( user["mobile"] != "" ) {
        if( !reMobile.test(user["mobile"]) ) {
          formatHint.push("簡訊:手機格式有誤");
          mobilePassed = false;
        } 
      } else {
        formatHint.push("簡訊:手機號碼未設定");
        mobilePassed = false;
      }
      
      var reAddress = new RegExp(/^\s*.{10,}\s*$/);
      if( user["address"] != "" ) {
        if( !reAddress.test(user["address"]) ) {
          formatHint.push("紙本:地址格式有誤");
          addressPassed = false;
        } 
      } else {
        formatHint.push("紙本:地址未設定");
        addressPassed = false;
      }
      
      if( user["email"] != "" ) {
        if( !checkEmail(user["email"]) ) {
          formatHint.push("Email:格式有誤");
          emailPassed = false;
        } 
      } else {
        formatHint.push("Email:未設定");
        emailPassed = false;
      }
      
      Logger.log(mobilePassed);
      Logger.log(addressPassed);
      Logger.log(emailPassed);
      
      if(mobilePassed && addressPassed && emailPassed) {
        appMsg('commSetupInfoLabel','讀取完成..請設定..',"blue");
      } else {
        formatHint.push("請回[基本資料設定]檢查,再回來設定");
        appMsg('commSetupInfoLabel',formatHint.toString(),"red");      
      }

      
      var sheet_config = openConfigSheet();
      //app.getElementById("actEMCheckbox").
      // actEMCheckbox actSMCheckbox majorEMCheckbox majorPACheckbox minorEMCheckbox minorPACheckbox   
      var config_act = {};
      config_act = getConfig(sheet,sheet_config,"隊號",loginID,"隊部活動通知方式");
      var config_minor = {};
      config_minor = getConfig(sheet,sheet_config,"隊號",loginID,"隊部次重點刊物通知方式");
      var config_major = {};
      config_major = getConfig(sheet,sheet_config,"隊號",loginID,"隊部重點刊物通知方式");
      
      
      Logger.log("config_act="+config_act);
      Logger.log("config_minor="+config_minor);
      Logger.log("config_major="+config_major);
      
      // bug: checkbox by default should be set with false
      
      Logger.log("mobilePassed="+mobilePassed);
      Logger.log("addressPassed="+addressPassed);
      Logger.log("emailPassed="+emailPassed);
      
      //actEMInfoLabel actSMInfoLabel majorEMInfoLabel majorPAInfoLabel minorEMInfoLabel minorPAInfoLabel
      if(mobilePassed) {
        app.getElementById("actSMCheckbox").setEnabled(true);
        app.getElementById("actSMInfoLabel").setEnabled(true).setStyleAttribute('color','black');
        app.getElementById("actSMCheckbox").setValue(config_act["SM"]); 
      }
      
      if(addressPassed) {
        app.getElementById("majorPACheckbox").setEnabled(true);
        app.getElementById("minorPACheckbox").setEnabled(true);
        app.getElementById("majorPAInfoLabel").setEnabled(true).setStyleAttribute('color','black');
        app.getElementById("minorPAInfoLabel").setEnabled(true).setStyleAttribute('color','black');        
        app.getElementById("minorPACheckbox").setValue(config_minor["PA"]);  
        app.getElementById("majorPACheckbox").setValue(config_major["PA"]);   
      }
      
      if(emailPassed) {
        app.getElementById("actEMCheckbox").setEnabled(true);
        app.getElementById("majorEMCheckbox").setEnabled(true);
        app.getElementById("minorEMCheckbox").setEnabled(true);
        app.getElementById("actEMInfoLabel").setEnabled(true).setStyleAttribute('color','black');
        app.getElementById("majorEMInfoLabel").setEnabled(true).setStyleAttribute('color','black');
        app.getElementById("minorEMInfoLabel").setEnabled(true).setStyleAttribute('color','black');               
        app.getElementById("actEMCheckbox").setValue(config_act["EM"]);
        app.getElementById("minorEMCheckbox").setValue(config_minor["EM"]);
        app.getElementById("majorEMCheckbox").setValue(config_major["EM"]);
      }           
    }   
  }
  
  
  app.getElementById("commChangeButton").setEnabled(true);
  app.getElementById("commBackButton").setEnabled(true);  
  return app;
}




function procCommChange(e){
  Logger.log(e);
  
  var app = UiApp.getActiveApplication();
  
  appMsg('commSetupInfoLabel',"","black");
  
  var sheet = openMemberSheet();
  var loginID = getLogin();
  
  var config_act = {};
  var config_minor = {};
  var config_major = {};
  
  for(var i in e.parameter) {
    if( i.indexOf("Checkbox")>-1 ) {
      if( i.indexOf("actSM")>-1 ) {
        if( e.parameter[i] == "true" ) config_act["SM"] = true;
      }
      if( i.indexOf("actEM")>-1 ) {
        if( e.parameter[i] == "true" ) config_act["EM"] = true;
      }
      if( i.indexOf("minorEM")>-1 ) {
        if( e.parameter[i] == "true" ) config_minor["EM"] = true;
      }
      if( i.indexOf("minorPA")>-1 ) {
        if( e.parameter[i] == "true" ) config_minor["PA"] = true;
      }
      if( i.indexOf("majorEM")>-1 ) {
        if( e.parameter[i] == "true" ) config_major["EM"] = true;
      }
      if( i.indexOf("majorPA")>-1 ) {
        if( e.parameter[i] == "true" ) config_major["PA"] = true;
      }
    }
  }
  
  
  // bug: no email but email is check in setup,this will confuse user.
  //隊部活動通知方式    隊部次重點刊物通知方式  隊部重點刊物通知方式
  if((setConfig(sheet,"隊號",loginID,"隊部活動通知方式",config_act) == null) ||
     (setConfig(sheet,"隊號",loginID,"隊部次重點刊物通知方式",config_minor) == null) ||
     (setConfig(sheet,"隊號",loginID,"隊部重點刊物通知方式",config_major) == null) ) {
    appMsg('commSetupInfoLabel','設定寫入錯誤!','red'); 
  } else {
    appMsg('commSetupInfoLabel','設定成功!','green'); 
  }
  
  app.getElementById("commChangeButton").setEnabled(true);
  app.getElementById("commBackButton").setEnabled(true);   
  
  return app; 
}



function procLicense(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();
  

  
  var sheet = openMemberSheet();
  var sheet_config = openConfigSheet();
  var loginID = getLogin();
  
  Logger.log("loginID="+loginID);

  
  var formContent = app.getElementById("licenseFormContent"); 
  
  
  Logger.log(formContent);
 
  
  var licenseConfig = {};
  licenseConfig = getConfigString(sheet_config,"證件代碼");      
  
  Logger.log(licenseConfig);

  
  var c=0;
  for(var i in licenseConfig) {
    ++c;
  }
  
    formContent.resize(5+c,18);
  
  
  var i2 = 2;
  for( var i in licenseConfig) {    
    formContent.setText(i2,1,licenseConfig[i]);
    Logger.log("1");
    
    Logger.log(i.toString());
    
        Logger.log("1.5");
    var l = i.toString();
    
    var date1YearText = app.createTextBox().setName(l+'date1YearText').setWidth('30');
    var date1MonthText = app.createTextBox().setName(l+'date1MonthText').setWidth('30');
    var date1DayText = app.createTextBox().setName(l+'date1DayText').setWidth('30');
Logger.log("2");
    var date2YearText = app.createTextBox().setName(l+'date2YearText').setWidth('30');
    var date2MonthText = app.createTextBox().setName(l+'date2MonthText').setWidth('30');
    var date2DayText = app.createTextBox().setName(l+'date2DayText').setWidth('30');
Logger.log("3");
    
    formContent.setText(i2,2,"民國");     
    formContent.setWidget(i2,3,date1YearText);
      formContent.setText(i2,4,"年");     
    formContent.setWidget(i2,5,date1MonthText);
      formContent.setText(i2,6,"月");    
    formContent.setWidget(i2,7,date1DayText);
   formContent.setText(i2,8,"日");       
       formContent.setText(i2,9,"- 民國");       
      formContent.setWidget(i2,10,date2YearText);
        formContent.setText(i2,11,"年");     
      formContent.setWidget(i2,12,date2MonthText);
    formContent.setText(i2,13,"月");      
      formContent.setWidget(i2,14,date2DayText);    
  formContent.setText(i2,15,"日");      
   
    var date1 = getValueByKey(sheet,"隊號",loginID,"證件發照日"+i);  
    Logger.log(date1);
        
    if(date1 != "") {
      date1 = new Date(date1);
      
      date1YearText.setText(date1.getFullYear()-1911);      
      date1MonthText.setText(date1.getMonth()+1);        
      date1DayText.setText(date1.getDate());    
    }
   
Logger.log("6");
    
    var date2 = getValueByKey(sheet,"隊號",loginID,"證件到期日"+i);
    Logger.log(date2);
    if(date2 != "") {      
      date2 = new Date(date2);
      
      date2YearText.setText(date2.getFullYear()-1911);      
      date2MonthText.setText(date2.getMonth()+1);        
      date2DayText.setText(date2.getDate());              
    }
    

    ++i2;
  }
 
  
  

  var backButton = app.getElementById("licenseBackButton");    
  formContent.setWidget(i2+1,0,backButton);
  
  var changeButton = app.getElementById("licenseChangeButton");    
  formContent.setWidget(i2+1,16,changeButton);

  
  
  appMsg('licenseInfoLabel','讀取完成,請使用民國年份,例如:100','blue'); 


  return app;
}  

function licenseDate() {
    this.date1year=null;
    this.date1month=null;
    this.date1day=null;
    this.date2year=null;
    this.date2month=null;
    this.date2day=null;
    this.passed=false;
    this.date1=null;
    this.date2=null;
    this.write=false;
}



function procLicenseChange(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();
  
  var formContent = app.getElementById("licenseFormContent"); 
  
  // 
  var ld = {};
  
  //ld['AA'] = new licenseDate();
  
    for(var i in e.parameter) {
      if( i.indexOf("Text")>-1 ) {
        
        var license = String(i).substring(0,2);
        
        Logger.log('license='+license);
        
        ld[license] = new licenseDate();
        
        ld[license].date1year = e.parameter[license+'date1YearText'];
        ld[license].date1month = e.parameter[license+'date1MonthText'];
        ld[license].date1day = e.parameter[license+'date1DayText'];
              
        ld[license].date2year = e.parameter[license+'date2YearText'];
        ld[license].date2month = e.parameter[license+'date2MonthText'];
        ld[license].date2day = e.parameter[license+'date2DayText'];
                
        
      }
      
    }
  

//  Logger.log(ld);

  var reYear = new RegExp(/^\s*[0-9]{2,3}\s*$/);  
  var reMonth = new RegExp(/^\s*(0[1-9]|[1-9]|1[012])\s*$/);  
  var reDay = new RegExp(/^\s*(0[1-9]|[1-9]|[12][0-9]|3[01])\s*$/);    
  
  for(var i in ld) {
    
    /*
   if(!reYear.test(ld[i].date1year)) {
      ld[i].passed = false;
      continue;
    }
    if(!reMonth.test(ld[i].date1month) ) {
      ld[i].passed = false;
      continue;
    }
    if(!reDay.test(ld[i].date1day)) {
      ld[i].passed = false;
      continue;
    }
    if(!reYear.test(ld[i].date2year) ) {
      ld[i].passed = false;
      continue;
    }
    if(!reMonth.test(ld[i].date2month) ) {
      ld[i].passed = false;
      continue;
    }
    if(!reDay.test(ld[i].date2day) ) {
      ld[i].passed = false;    
      continue;
    }
    */
      
    if( reYear.test(ld[i].date1year) && 
       reMonth.test(ld[i].date1month)  && 
       reDay.test(ld[i].date1day) &&
       reYear.test(ld[i].date2year) &&
       reMonth.test(ld[i].date2month) && 
       reDay.test(ld[i].date2day) ) {
      
      ld[i].passed = true; 
      ld[i].write = true; 
    } 
    
    
    if( (ld[i].date1year=="") && 
       (ld[i].date1month=="")  && 
       (ld[i].date1day=="") &&
       (ld[i].date2year=="") &&
       (ld[i].date2month=="") && 
      (ld[i].date2day=="") ) {
      
         ld[i].passed = true;
      ld[i].write = false; 
    } 
    
    ld[i].date1 = new Date(parseInt(ld[i].date1year)+1911,ld[i].date1month-1,ld[i].date1day);
    ld[i].date2 = new Date(parseInt(ld[i].date2year)+1911,ld[i].date2month-1,ld[i].date2day);
    
    if(ld[i].date1>ld[i].date2) {
      ld[i].passed = false;    
      ld[i].write = false; 
    }
  }
  


 // var errmsg = new Array();
  
  for(var i in ld) { 
    if( !(ld[i].passed) ) {
       appMsg('licenseInfoLabel','日期有錯,請檢查.','error'); 
      app.getElementById("licenseBackButton").setEnabled(true); 
app.getElementById("licenseChangeButton").setEnabled(true); 
      return app;
    }
  }
       
  
    var sheet = openMemberSheet();
  var sheet_config = openConfigSheet();

  
  var loginID = getLogin();
  
  var keys = new Array();
  for( var i in ld) {
 
      keys.push("證件發照日"+i);
     keys.push("證件到期日"+i); 
 
   }
  var range = new Array();
  range = getRangeByKeys(sheet,"隊號",loginID,keys);  
  
  
  
  
  var i2=0;
  for( var i in ld) { 
        if(ld[i].write) {
          Logger.log("i="+i);
          Logger.log("ld="+ld[i]);
    range[i2].setValue(ld[i].date1);
    range[i2+1].setValue(ld[i].date2);
          
        } else {
       range[i2].clear();
    range[i2+1].clear();       
        }
    
    
    i2 = i2 + 2;
  }
  
  appMsg('licenseInfoLabel','資料寫入成功!','green'); 
  
  
  //{AC={date2year=34, date1day=33, date1month=32, passed=false, date2month=35, date1year=31, date2=null, date2day=36, date1=null}, AD={date2year=44, date1day=43, date1month=42, passed=false, date2month=45, date1year=41, date2=null, date2day=46, date1=null}, AA={date2year=2012, date1day=13, date1month=12, passed=false, date2month=1, date1year=2013, date2=Wed Feb 01 08:00:00 PST 2012, date2day=2, date1=Sun Jan 12 08:00:00 PST 2014}, AB={date2year=2099, date1day=2, date1month=1, passed=true, date2month=1, date1year=1900, date2=Mon Feb 02 08:00:00 PST 2099, date2day=3, date1=Thu Feb 01 08:00:00 PST 1900}, AG={date2year=74, date1day=73, date1month=72, passed=false, date2month=75, date1year=71, date2=null, date2day=76, date1=null}, AH={date2year=84, date1day=83, date1month=82, passed=false, date2month=85, date1year=81, date2=null, date2day=86, date1=null}, AE={date2year=54, date1day=53, date1month=52, passed=false, date2month=55, date1year=51, date2=null, date2day=56, date1=null}, AF={date2year=64, date1day=63, date1month=62, passed=false, date2month=65, date1year=61, date2=null, date2day=66, date1=null}}
  
  //{AC={date2year=34, date1day=33, date1month=32, passed=false, date2month=35, date1year=31, date2=Mon Jan 04 08:00:00 PST 1937, date2day=36, date1=Mon Oct 02 08:00:00 PST 1933}, AD={date2year=44, date1day=43, date1month=42, passed=false, date2month=45, date1year=41, date2=Fri Nov 14 08:00:00 PST 1947, date2day=46, date1=Fri Aug 11 08:00:00 PDT 1944}, AA={date2year=2012, date1day=13, date1month=12, passed=false, date2month=1, date1year=2013, date2=Wed Feb 01 08:00:00 PST 2012, date2day=2, date1=Sun Jan 12 08:00:00 PST 2014}, AB={date2year=2099, date1day=2, date1month=1, passed=true, date2month=1, date1year=1900, date2=Mon Feb 02 08:00:00 PST 2099, date2day=3, date1=Thu Feb 01 08:00:00 PST 1900}, AG={date2year=74, date1day=73, date1month=72, passed=false, date2month=75, date1year=71, date2=Sat Jun 14 09:00:00 PDT 1980, date2day=76, date1=Sun Mar 13 08:00:00 PST 1977}, AH={date2year=84, date1day=83, date1month=82, passed=false, date2month=85, date1year=81, date2=Fri Apr 26 09:00:00 PDT 1991, date2day=86, date1=Thu Jan 21 08:00:00 PST 1988}, AE={date2year=54, date1day=53, date1month=52, passed=false, date2month=55, date1year=51, date2=Wed Sep 24 08:00:00 PDT 1958, date2day=56, date1=Tue Jun 21 08:00:00 PDT 1955}, AF={date2year=64, date1day=63, date1month=62, passed=false, date2month=65, date1year=61, date2=Mon Aug 04 08:00:00 PDT 1969, date2day=66, date1=Sun May 01 08:00:00 PDT 1966}}
  //{AC={date2year=34, date1day=33, date1month=32, passed=false, date2month=35, date1year=31, date2day=36}, AD={date2year=44, date1day=43, date1month=42, passed=false, date2month=45, date1year=41, date2day=46}, AA={date2year=2012, date1day=13, date1month=12, passed=true, date2month=1, date1year=2011, date2day=2}, AB={date2year=2099, date1day=2, date1month=1, passed=true, date2month=1, date1year=1900, date2day=3}, AG={date2year=74, date1day=73, date1month=72, passed=false, date2month=75, date1year=71, date2day=76}, AH={date2year=84, date1day=83, date1month=82, passed=false, date2month=85, date1year=81, date2day=86}, AE={date2year=54, date1day=53, date1month=52, passed=false, date2month=55, date1year=51, date2day=56}, AF={date2year=64, date1day=63, date1month=62, passed=false, date2month=65, date1year=61, date2day=66}}
    Logger.log(ld);
  // 改使用有效期限,例如:三年..
  /*
  {parameter={
  AEdate1DayText=, 
  AGdate1DayText=, 
    ABdate1MonthText=1, 
      ABdate2MonthText=, ctrl=false, 
        AFdate1DayText=, 
          AGdate1MonthText=, 
            button=1, AHdate1DayText=, AAdate2MonthText=, AEdate1MonthText=, ACdate2MonthText=, ADdate1YearText=, ADdate1MonthText=, ACdate1MonthText=, AHdate2YearText=, AAdate1YearText=, clientY=308, AEdate2DayText=, AAdate1MonthText=, clientX=593, ACdate2YearText=, AEdate2MonthText=, AFdate2DayText=, ADdate2YearText=, AFdate1MonthText=, AHdate1YearText=, ABdate2DayText=, AEdate1YearText=, AGdate2DayText=, AFdate2MonthText=, AAdate2DayText=, ABdate1DayText=3, eventType=click, AHdate2MonthText=, meta=false, ADdate1DayText=, AGdate2MonthText=, alt=false, ABdate2YearText=, ACdate2DayText=, AFdate1YearText=, screenY=749, screenX=1012, ACdate1YearText=, ACdate1DayText=, AHdate2DayText=, ABdate1YearText=2012, ADdate2DayText=, AAdate1DayText=, ADdate2MonthText=, AAdate2YearText=, AGdate1YearText=, source=licenseChangeButton, AFdate2YearText=, AHdate1MonthText=, AGdate2YearText=, AEdate2YearText=, y=23.833343505859375, shift=false, x=39.66668701171875}}
*/
  
  
  /*
  for(var i in e.parameter) {
    if( i.indexOf("Checkbox")>-1 ) {
      if( i.indexOf("actSM")>-1 ) {
        if( e.parameter[i] == "true" ) config_act["SM"] = true;
      }
      if( i.indexOf("actEM")>-1 ) {
        if( e.parameter[i] == "true" ) config_act["EM"] = true;
      }
      if( i.indexOf("minorEM")>-1 ) {
        if( e.parameter[i] == "true" ) config_minor["EM"] = true;
      }
      if( i.indexOf("minorPA")>-1 ) {
        if( e.parameter[i] == "true" ) config_minor["PA"] = true;
      }
      if( i.indexOf("majorEM")>-1 ) {
        if( e.parameter[i] == "true" ) config_major["EM"] = true;
      }
      if( i.indexOf("majorPA")>-1 ) {
        if( e.parameter[i] == "true" ) config_major["PA"] = true;
      }
    }
  }
  
    
  */
  
  
app.getElementById("licenseBackButton").setEnabled(true); 
app.getElementById("licenseChangeButton").setEnabled(true); 

  
  return app;
}  

function procLogout(e){
  Logger.log(e);
  var app = UiApp.getActiveApplication();
  
  
  return app;
}
